#include "mrmusic.h"
#include "ui_mrmusic.h"

#include <QIcon>
#include <QGraphicsDropShadowEffect>
#include <QMouseEvent>
#include <QDebug>
#include <QFileDialog>
#include <QMediaPlaylist>
#include <QSystemTrayIcon>
#include <QSqlQuery>
#include <QSqlError>
#include <QMenu>
#include <QMessageBox>
#include "recbox.h"
#include "recboxitem.h"
#include "commonpage.h"

mrMusic::mrMusic(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::mrMusic)
{
    ui->setupUi(this);

    initUI();

    initSqlite();

    initMusicList();

    //媒体播放控制相关
    initPlayer();
}

mrMusic::~mrMusic()
{
    delete ui;
}

void mrMusic::initUI()
{
    this->setWindowIcon(QIcon(":/images/mrMusicPicture.png"));
    setWindowFlag(Qt::FramelessWindowHint);
    ui->max->setEnabled(false);

    //设置窗口阴影
    setAttribute(Qt::WA_TranslucentBackground); //设置背景为半透明

    QGraphicsDropShadowEffect* shadowEffect = new QGraphicsDropShadowEffect(this);

    shadowEffect->setOffset(0, 0);
    shadowEffect->setColor("#000000"); //black
    shadowEffect->setBlurRadius(10);

    setGraphicsEffect(shadowEffect);

    //设置 BtForm 的图标和信息
    ui->rec->setIconAndText(":/images/rec", "推荐", 0);
    ui->audio->setIconAndText(":/images/audio", "电台", 1);
    ui->music->setIconAndText(":/images/music", "音乐馆", 2);
    ui->like->setIconAndText(":/images/like", "喜欢", 3);
    ui->local->setIconAndText(":/images/local", "本地下载", 4);
    ui->recent->setIconAndText(":/images/recent", "最近播放", 5);

    //默认 local 开启动画的效果
    ui->local->showAnimation(true);

    srand((unsigned int)time(NULL));
    ui->recMusicBox->initBoxItemUi(randomPicture(), 1);
    ui->recSupplyBox->initBoxItemUi(randomPicture(), 2);

    //设置 commonpage 信息
    ui->likePage->setCommonPageUI("我的喜欢", ":/rec/019.png");
    ui->localPage->setCommonPageUI("本地音乐", ":/images/localMusicImage.png");
    ui->recentPage->setCommonPageUI("历史播放", ":/rec/029.png");

    //设置默认图标
    QString style = "background-image: url(";
    style += ":/images/play.png";
    style += ");";
    ui->play->setStyleSheet(style);

    style.replace("play", "shuffle");
    ui->playMode->setStyleSheet(style);

    //音量调节界面
    volumeTool = new VolumeTool(this);

    // lrc 歌词界面
    lrcPage = new LrcPage(this);
    lrcPage->hide();

    //添加系统托盘
    QSystemTrayIcon* trayIcon = new QSystemTrayIcon(this);
    trayIcon->setIcon(QIcon(":/images/mrMusicPicture.png"));
    trayIcon->show();

    //添加托盘菜单
    QMenu* trayMenu = new QMenu();
    trayMenu->addAction("显示", this, &QWidget::showNormal);
    trayMenu->addAction("退出", this, &mrMusic::onMrMusicQuit);
    trayIcon->setContextMenu(trayMenu);

    connectSignalsAndSlots();
}

void mrMusic::initPlayer()
{
    //创建播放器
    player = new QMediaPlayer(this);

    //创建播放列表
    playlist = new QMediaPlaylist(this);

    //设置播放模式为循环播放
    playlist->setPlaybackMode(QMediaPlaylist::Loop);

    //将播放列表设置给播放器
    player->setPlaylist(playlist);

    // QMediaPlayer 信号和槽函数关联
    connect(player, &QMediaPlayer::stateChanged, this, &mrMusic::onPlayerStateChanged);
    connect(playlist, &QMediaPlaylist::playbackModeChanged, this, &mrMusic::onPlayBackModeChanged);
    connect(playlist, &QMediaPlaylist::currentIndexChanged, this, &mrMusic::onCurrentIndexChanged);

    //同步播放时间
    connect(player, &QMediaPlayer::durationChanged, this, &mrMusic::onDurationChanged);
    connect(player, &QMediaPlayer::positionChanged, this, &mrMusic::onPositionChanged);

    //同步歌曲名称、歌手、封面图片
    connect(player, &QMediaPlayer::metaDataAvailableChanged, this, &mrMusic::onMetaDataAvailableChanged);
}

void mrMusic::mousePressEvent(QMouseEvent *event)
{
    if(event->button() == Qt::LeftButton)
    {
        isDrag = true;
        dragPosition = event->globalPos() - frameGeometry().topLeft();
        return;
    }
    QWidget::mousePressEvent(event);
}

void mrMusic::mouseMoveEvent(QMouseEvent *event)
{
    if(isDrag && event->buttons() == Qt::LeftButton)
    {
        move(event->globalPos() - dragPosition);
    }
    QWidget::mouseMoveEvent(event);
}

void mrMusic::connectSignalsAndSlots()
{
    // BTForm 界面
    connect(ui->rec, &BTForm::btClick, this, &mrMusic::onBtFormClick);
    connect(ui->audio, &BTForm::btClick, this, &mrMusic::onBtFormClick);
    connect(ui->music, &BTForm::btClick, this, &mrMusic::onBtFormClick);
    connect(ui->like, &BTForm::btClick, this, &mrMusic::onBtFormClick);
    connect(ui->local, &BTForm::btClick, this, &mrMusic::onBtFormClick);
    connect(ui->recent, &BTForm::btClick, this, &mrMusic::onBtFormClick);
    connect(ui->localPage, &CommonPage::upDateLikeMusic, this, &mrMusic::upDateLikeMusics);

    //播放控制区信号和槽函数关联
    connect(ui->play, &QPushButton::clicked, this, &mrMusic::onPlayClicked);
    connect(ui->playUp, &QPushButton::clicked, this, &mrMusic::onPlayUpClicked);
    connect(ui->playDown, &QPushButton::clicked, this, &mrMusic::onPlayDownClicked);
    connect(ui->playMode, &QPushButton::clicked, this, &mrMusic::onPlayModeClicked);

    //播放所有音乐
    connect(ui->likePage, &CommonPage::playAllMusic, this, &mrMusic::onPlayAllMusic);
    connect(ui->localPage, &CommonPage::playAllMusic, this, &mrMusic::onPlayAllMusic);
    connect(ui->recentPage, &CommonPage::playAllMusic, this, &mrMusic::onPlayAllMusic);

    //双击播放音乐
    connect(ui->likePage, &CommonPage::playMusicByIndex, this, &mrMusic::playMusicByIndex);
    connect(ui->localPage, &CommonPage::playMusicByIndex, this, &mrMusic::playMusicByIndex);
    connect(ui->recentPage, &CommonPage::playMusicByIndex, this, &mrMusic::playMusicByIndex);

    //音量控制相关
    connect(volumeTool, &VolumeTool::setSilence, this, &mrMusic::setMusicSilence);
    connect(volumeTool, &VolumeTool::renewVolume, this, &mrMusic::setMusicVolume);

    //进度条相关
    connect(ui->processBar, &musicSlider::setSliderPosition, this, &mrMusic::onMusicSliderChanged);

    // lrc 界面相关
    connect(ui->lyric, &QPushButton::clicked, this, &mrMusic::onLyricClicked);
    connect(lrcPage, &LrcPage::setLrcAmination, this, &mrMusic::onHideBtnClicked);
}

void mrMusic::onBtFormClick(int pageId)
{
    //利用 QList 来处理点击时的颜色
    QList<BTForm*> btFormList = this->findChildren<BTForm*>();
    for(auto& btForm: btFormList)
    {
        if(btForm->getPageId() != pageId)
        {
            btForm->clearBackground();
        }
    }

    ui->stackedWidget->setCurrentIndex(pageId);
    isDrag = false;
}

void mrMusic::upDateLikeMusics(bool isLike, const QString &musicId)
{
    auto it = musicList.findMusicByMusicId(musicId);
    if(it != musicList.end())
    {
        it->setIsLike(isLike);
    }
    ui->likePage->upDateMusic(musicList);
    ui->localPage->upDateMusic(musicList);
    ui->recentPage->upDateMusic(musicList);
}

QJsonArray mrMusic::randomPicture()
{
    QVector<QString> vectorImageName;
    vectorImageName << "001.png" << "003.png" << "004.png" << "005.png" << "006.png" << "007.png"
                 << "008.png" << "009.png" << "010.png" << "011.png" << "012.png" << "013.png"
                 << "014.png" << "015.png" << "016.png" << "017.png" << "018.png" << "019.png"
                 << "020.png" << "021.png" << "022.png" << "023.png" << "024.png" << "025.png"
                 << "026.png" << "027.png" << "028.png" << "029.png" << "030.png" << "031.png"
                 << "032.png" << "033.png" << "034.png" << "035.png" << "036.png" << "037.png"
                 << "038.png" << "039.png" << "040.png";

    std::random_shuffle(vectorImageName.begin(), vectorImageName.end());

    QJsonArray objArray;
    for(int i = 0; i < vectorImageName.size(); i++)
    {
        QJsonObject obj;
        obj.insert("path", ":/rec/" + vectorImageName[i]);

        QString strText = QString("推荐-%1").arg(i, 3, 10, QChar('0'));
        obj.insert("text", strText);

        objArray.append(obj);
    }

    return objArray;
}

void mrMusic::onPlayClicked()
{
    qDebug() << "播放按钮点击";
    if(player->state() == QMediaPlayer::PlayingState)
    {
        player->pause();
    }
    else if(player->state() == QMediaPlayer::PausedState)
    {
        player->play();
    }
    else if(player->state() == QMediaPlayer::StoppedState)
    {
        player->play();
    }
}

void mrMusic::onPlayerStateChanged()
{
    qDebug() << "播放状态改变";
    QString style = "background-image: url(";
    style += ":/images/play.png";
    style += ");";
    if(player->state() == QMediaPlayer::PlayingState)
    {
        style.replace("play", "pause");
    }
    ui->play->setStyleSheet(style);
}

void mrMusic::onPlayUpClicked()
{
    playlist->previous();
}

void mrMusic::onPlayDownClicked()
{
    playlist->next();
}

void mrMusic::onPlayModeClicked()
{
    if(playlist->playbackMode() == QMediaPlaylist::Loop)
    {
        qDebug() << "随机播放";
        playlist->setPlaybackMode(QMediaPlaylist::Random);
    }
    else if(playlist->playbackMode() == QMediaPlaylist::Random)
    {
        qDebug() << "单曲循环播放";
        playlist->setPlaybackMode(QMediaPlaylist::CurrentItemInLoop);
    }
    else if(playlist->playbackMode() == QMediaPlaylist::CurrentItemInLoop)
    {
        qDebug() << "列表循环播放";
        playlist->setPlaybackMode(QMediaPlaylist::Loop);
    }
    else qDebug() << "暂未支持该播放模式";
}

void mrMusic::onPlayBackModeChanged()
{
    QString style = "background-image: url(";
    style += ":/images/list_play.png";
    style += ");";

    if(playlist->playbackMode() == QMediaPlaylist::Loop)
    {
        ui->playMode->setStyleSheet(style);
    }
    else if(playlist->playbackMode() == QMediaPlaylist::Random)
    {
        style.replace("list_play", "shuffle");
        style.replace("single_play", "shuffle");
        ui->playMode->setStyleSheet(style);
    }
    else if(playlist->playbackMode() == QMediaPlaylist::CurrentItemInLoop)
    {
        style.replace("list_play", "single_play");
        style.replace("shuffle", "single_play");
        ui->playMode->setStyleSheet(style);
    }
    else qDebug() << "暂未支持该播放模式";
}

void mrMusic::onPlayAllMusic(PageType pageType)
{
    switch (pageType)
    {
        case LIKE_PAGE:
        {
            currentPage = ui->likePage;
            updateBtFormAnimation();
            break;
        }
        case LOCAL_PAGE:
        {
            currentPage = ui->localPage;
            updateBtFormAnimation();
            break;
        }
        case RECENT_PAGE:
        {
            currentPage = ui->recentPage;
            updateBtFormAnimation();
            break;
        }
        default: qDebug() << "待扩展";
    }

    playAllOfCommonPage(currentPage, 0);
}

void mrMusic::playAllOfCommonPage(CommonPage *page, int index)
{
    currentPage = page;
    updateBtFormAnimation();

    playlist->clear();

    page->addMusicToPlaylist(musicList, playlist);
    playlist->setCurrentIndex(index);
    player->play();
}

void mrMusic::playMusicByIndex(CommonPage *page, int index)
{
    playAllOfCommonPage(page, index);
}

void mrMusic::onCurrentIndexChanged(int index)
{
    currentIndex = index;
    const QString& musicId = currentPage->getMusicByIndex(index);
    auto it = musicList.findMusicByMusicId(musicId);
    if(it != musicList.end())
    {
        it->setIsHistory(true);
    }
    ui->recentPage->upDateMusic(musicList);
}

void mrMusic::setMusicSilence(bool isMuted)
{
    qDebug() << "setMusicSilence";
    player->setMuted(isMuted);
}

void mrMusic::setMusicVolume(int volumeRatio)
{
    player->setVolume(volumeRatio);
}

void mrMusic::onDurationChanged(qint64 duration)
{
    totalDuration = duration;
    int minute = duration / 1000 / 60;
    int second = duration / 1000 % 60;
    ui->totalTime->setText(QString("%1:%2").arg(minute, 2, 10, QChar('0'))
                           .arg(second, 2, 10, QChar('0')));
}

void mrMusic::onPositionChanged(qint64 duration)
{
    int minute = duration / 1000 / 60;
    int second = duration / 1000 % 60;
    ui->currentTime->setText(QString("%1:%2").arg(minute, 2, 10, QChar('0'))
                             .arg(second, 2, 10, QChar('0')));

    ui->processBar->renewSliderPosition(duration * 1.0 / totalDuration);

    //显示歌词到界面
    if(currentIndex >= 0)
    {
        lrcPage->showLrcWordLine(duration);
    }
}

void mrMusic::onMusicSliderChanged(double rate)
{
    qint64 total = player->duration();
    qint64 current = (qint64)(total * rate);

    int minute = current / 1000 / 60;
    int second = current / 1000 % 60;
    ui->currentTime->setText(QString("%1:%2").arg(minute, 2, 10, QChar('0'))
                             .arg(second, 2, 10, QChar('0')));

    player->setPosition(current);
}

void mrMusic::onMetaDataAvailableChanged(bool available)
{
    (void) available;
    QString musicName = "Unknown Music";
    QString musicSinger = "Unknown Singer";
    QString musicId = currentPage->getMusicByIndex(currentIndex);
    auto it = musicList.findMusicByMusicId(musicId);
    if(it != musicList.end())
    {
        musicName = it->getMusicName();
        musicSinger = it->getMusicSinger();
    }
    ui->musicName->setText(musicName);
    ui->musicSinger->setText(musicSinger);

    //获取封面图
    QVariant coverImage = player->metaData("ThumbnailImage");
    if(!coverImage.isValid())
    {
        //设置默认图片
        QString imagePath = ":/rec/007.png";
        ui->musicCover->setPixmap(imagePath);
        currentPage->setMusicImage(imagePath);
    }
    else
    {
        QImage image = coverImage.value<QImage>();
        ui->musicCover->setPixmap(QPixmap::fromImage(image));
        currentPage->setMusicImage(QPixmap::fromImage(image));
    }
    ui->musicCover->setScaledContents(true);

    //解析 lrc 歌词
    if(it != musicList.end())
    {
        //获取 lrc 歌词
        QString lrcPath = it->getLrcFilePath();

        lrcPage->parseMusicLrcFile(lrcPath);
    }

    //修改标题作者
    lrcPage->setMusicName(musicName);
    lrcPage->setMusicSinger(musicSinger);
}

void mrMusic::onLyricClicked()
{
    lrcPage->show();
    lrcShowAnimation = new QPropertyAnimation(lrcPage, "geometry", this);
    lrcShowAnimation->setDuration(250);
    lrcShowAnimation->setStartValue(QRect(10, lrcPage->height(), lrcPage->width(), lrcPage->height()));
    lrcShowAnimation->setEndValue(QRect(10, 10, lrcPage->width(), lrcPage->height()));
    lrcShowAnimation->start();
}

void mrMusic::onHideBtnClicked()
{
    lrcHideAnimation = new QPropertyAnimation(lrcPage, "geometry", this);
    lrcHideAnimation->setDuration(250);
    lrcHideAnimation->setStartValue(QRect(10, 10, lrcPage->width(), lrcPage->height()));
    lrcHideAnimation->setEndValue(QRect(10, lrcPage->height(), lrcPage->width(), lrcPage->height()));
    lrcHideAnimation->start();

    connect(lrcHideAnimation, &QPropertyAnimation::finished, this, [=]()
    {
        lrcPage->hide();
    });
}

void mrMusic::initSqlite()
{
    //1.导入数据库驱动
    sqlite = QSqlDatabase::addDatabase("QSQLITE");

    //2.设置数据库名称
    sqlite.setDatabaseName("MrMusicDB.db");

    //check
    if(!sqlite.open())
    {
        QMessageBox::critical(this, "MrMusicDB", "数据库[MrMusicDB.db]打开失败！");
        return;
    }
    qDebug() << "数据库[MrMusicDB.db]创建成功";

    //3.创建表
    QString sql("CREATE TABLE IF NOT EXISTS musicInfo( \
                    id INTEGER PRIMARY KEY AUTOINCREMENT,\
                    musicId varchar(50) UNIQUE,\
                    musicName varchar(50),\
                    musicSinger varchar(50),\
                    musicAlbum varchar(50),\
                    musicUrl varchar(256),\
                    duration BIGINT,\
                    isLike INTEGER,\
                    isHistory INTEGER \
                    )");
    QSqlQuery query;
    if(!query.exec(sql))
    {
        QMessageBox::critical(this, "MrMusic", "歌曲初始化错误！");
    }
    qDebug() << "创建表[musicInfo]成功";
}

void mrMusic::onMrMusicQuit()
{
    //更新数据库
    musicList.writeToDB();

    //断开与数据库的链接
    sqlite.close();

    //关闭窗口
    close();
}

void mrMusic::initMusicList()
{
    musicList.readFromDB();

    ui->likePage->setPageType(PageType::LIKE_PAGE);
    ui->likePage->upDateMusic(musicList);

    ui->localPage->setPageType(PageType::LOCAL_PAGE);
    ui->localPage->upDateMusic(musicList);

    ui->recentPage->setPageType(PageType::RECENT_PAGE);
    ui->recentPage->upDateMusic(musicList);
}

void mrMusic::updateBtFormAnimation()
{
    int index = ui->stackedWidget->indexOf(currentPage);
    if(index == -1)
    {
        qDebug() << "该页面不存在";
        return;
    }
    QList<BTForm*> btForms = this->findChildren<BTForm*>();
    for(auto& btForm : btForms)
    {
        if(btForm->getPageId() == index)
        {
            btForm->showAnimation(true);
        }
        else btForm->showAnimation(false);
    }
}

void mrMusic::on_quit_clicked()
{
    hide();
}

//显示音量调节
void mrMusic::on_volume_clicked()
{
    //先计算 ui->volume 左上角像素的全局坐标
    QPoint point = ui->volume->mapToGlobal(QPoint(0, 0));

    //计算出音量界面出现的位置坐标
    QPoint volumeToolLeftTop = point - QPoint(volumeTool->width() / 3, volumeTool->height());

    //移动到该位置
    volumeTool->move(volumeToolLeftTop);

    volumeTool->show();
}

void mrMusic::on_addLocal_clicked()
{
    QFileDialog* fileDialog = new QFileDialog(nullptr, "添加本地音乐");

    //设置文件对话框默认打开路径
    QDir dir(QDir::currentPath());
    dir.cdUp();
    QString musicPath = dir.path();
    musicPath += "/mrMusic/musics";
    fileDialog->setDirectory(musicPath);

    //fileDialog->setAcceptMode(QFileDialog::AcceptOpen);

    //设置文件过滤器
    //fileDialog->setWindowTitle("添加本地音乐");
    //fileDialog->setNameFilter("代码文件(*.h *.c *.hpp *.cpp)");

    //设置一次性打开多个文件
    fileDialog->setFileMode(QFileDialog::ExistingFiles);

    // MIME 类型
    QStringList mimeTypeFilters;
    mimeTypeFilters << "application/octet-stream" << "image/jpeg" << "image/png";
    fileDialog->setMimeTypeFilters(mimeTypeFilters);

    if(fileDialog->exec() == QDialog::Accepted)
    {
        QList<QUrl> fileUrls = fileDialog->selectedUrls();

        //拿到歌曲文件后，交由 musicList 来管理
        musicList.addMusicByUrls(fileUrls);

        //切换到本地下载页面
        ui->stackedWidget->setCurrentIndex(4);
        currentPage = ui->localPage;

        ui->localPage->upDateMusic(musicList);

        //将 localPage 中的歌曲添加到播放列表中
        ui->localPage->addMusicToPlaylist(musicList, playlist);
    }
}

void mrMusic::on_min_clicked()
{
    showMinimized();
}

void mrMusic::on_skin_clicked()
{
    QMessageBox::information(this, "温馨提示", "换肤功能暂未支持...");
}
